/*
 * @Author: yangzonglong
 * @Date: 2021-03-01 13:18:46
 * @version: v1.0.0
 * @Descripttion:
 * @LastEditors: 木易宗龙 871387321@qq.com
 * @LastEditTime: 2023-11-12 18:38:14
 * @Auditor:
 */
import React, { useCallback, useState, useImperativeHandle, forwardRef, useEffect, useMemo, useRef } from 'react';
import { Select } from 'antd';
import Icon from '../../icon/Icon';
import { getTableModalOptions } from '../../../util';
import { units, ModalTableInModel } from '@library';
import styles from './style.module.scss';
import { message } from '@library/utils';

const style = {
  color: "rgba(35,37,40, 0.45)",
  pointerEvents: "auto"
};

interface RefProps {
  getData(): any;
}

const copyToClipboard = (value: string) => {
  const textarea = document.createElement('textarea');
  textarea.value = value;
  document.body.appendChild(textarea);
  textarea.select();
  document.execCommand('copy');
  document.body.removeChild(textarea);
  message.success('复制成功');
};

const getNames = (showFieldName: string | string[], next: any) => {
  if (typeof showFieldName === 'string') {
    return next?.[showFieldName];
  } else {
    let str = showFieldName.reduce((all: string, now: any, index: number) => {
      return all + next[now.value] + (index === showFieldName.length - 1 ? '' : '-');
    }, '');
    console.log(str, '---');

    return str;
  }
};

const App = (props: any, ref: React.Ref<RefProps>) => {

  const { value, disabled, options, onDataLinkChange, item, scriptsChangeData, getCurrInterceptors } = props;

  const count = useRef(0);
  const cacheData = useRef(scriptsChangeData[options?.bindName]);
  const doubleClickRef = useRef<any>(null);
  const [visible, setVisible] = useState(false);
  const [v, setV] = useState('');
  const [model, setModel] = useState<any>({});
  const timeoutRef = useRef<any>(null);
  const modalTableRef = useRef<any>(null);
  const [list, setList] = useState<any[]>([]);
  const [open, setOpen] = useState(false);

  const onOk = (rows: object[], resetList = true) => {
    let v = '';
    let _rows = {};
    const mapFileds = options.mapFileds || {};

    options?.filedShowName.forEach((item: any) => {
      _rows[mapFileds?.[item.value] || item.value] = rows.reduce((all: any, now: any, index: number) => {
        return all + (index === 0 ? '' : ' ') + (now[item.value] || '');
      }, '');
    });

    options?.extraFieldName?.forEach((item: any) => {
      _rows[mapFileds?.[item.value] || item.value] = rows.reduce((all: any, now: any, index: number) => {
        if (typeof now[item.value] === 'object') {
          if (typeof all === 'string') all = [];
          all.push(now[item.value]);

          if (index === rows.length - 1) {
            if (all.length === 1) all = all[0];
          }

          return all;
        }
        return all + (index === 0 ? '' : ' ') + (now[item.value] || '');
      }, '');
    });

    if (Array.isArray(options?.showFieldName)) {
      for (let index = 0; index < options?.showFieldName.length; index++) {
        const element = options?.showFieldName[index].value;

        _rows[mapFileds?.[element] || element] = rows.reduce((all: any, now: any, index: number) => {
          return all + (index === 0 ? '' : ' ') + (now[element] || '');
        }, '');

        _rows[element] = _rows[mapFileds?.[element] || element];

      }
      v = getNames(options?.showFieldName, _rows) || '';
      if (v?.replaceAll('-', '').trim() === '') {
        v = '';
      }
      setV(v);
    } else {
      _rows[mapFileds?.[options?.showFieldName] || options?.showFieldName] = rows.reduce((all: any, now: any, index: number) => {
        return all + (index === 0 ? '' : ' ') + (now[options?.showFieldName] || '');
      }, '');

      _rows[options?.showFieldName] = _rows[mapFileds?.[options?.showFieldName] || options?.showFieldName];
      v = _rows[options?.showFieldName] || '';
      setV(_rows[options?.showFieldName] || '');
    }

    setVisible(false);
    onDataLinkChange?.(_rows, v);
    setOpen(false);
    if (resetList) setList(rows);
  };

  useEffect(() => {
    if (!scriptsChangeData[options?.bindName] && count.current === 0) return;

    if (count.current === 0) {
      count.current = 1;
    } else {
      if (JSON.stringify(cacheData.current) !== JSON.stringify(scriptsChangeData[options?.bindName])) {
        cacheData.current = scriptsChangeData[options?.bindName];
        onOk([{}]);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [scriptsChangeData[options?.bindName]]);

  useEffect(() => {
    if (value === undefined) {
      setV('');
    } else if (value !== undefined) {
      setV(prev => value ? value : prev);
    }
  }, [value]);

  const _columns = useMemo(
    () => props?.columns?.filter((item: any) => item.dataIndex === props._dataIndex),
    [props]);

  const onShow = useCallback(() => {
    setModel(getTableModalOptions(
      localStorage.i18nextLng === 'en' ? _columns?.[0]?.['titleEn'] : _columns?.[0]?.['title'],
      options,
      scriptsChangeData,
      item,
      getCurrInterceptors
    ));
    setVisible(true);
  }, [_columns, options, scriptsChangeData, item, getCurrInterceptors]);

  const onHide = useCallback(() => setVisible(false), []);

  useImperativeHandle(ref, () => ({
    getData() {
      return v;
    },
  }));

  const handleQuerySet = (query: any) => {
    const currInterceptors = getCurrInterceptors?.(model.url);

    if (currInterceptors?.set) {
      return currInterceptors.set(query, item) || query;
    }
    return query;
  };

  function handleResult(result: { count: number; rows: any[]; }) {
    // 如果不支持分页 截取前200条 避免页面大数据页面渲染报错
    const rows = result?.rows?.slice(0, 200);

    rows?.forEach((item, index) => {
      if (!item.id) item.id = 'MOCK_' + index;
    });

    const currInterceptors = getCurrInterceptors(model.url);
    if (currInterceptors?.get) return currInterceptors.get(result);

    return { rows, count: result.count };
  }

  let url = options.modulesUrl ? options.modulesUrl : `/bk/api/${options.serviceModuleCode}/${options.modulesName}/find`;

  const onSearch = async (value: string) => {
    if (!value) return setOpen(false);

    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }

    timeoutRef.current = setTimeout(async () => {
      const query = modalTableRef.current.getSearchQuery(value, options.filedShowName.map((item: any) => item.value));
      const res = await units.serverLoading(url, query);
      const handleRes = handleResult(res);
      setList(handleRes.rows);
      setOpen(true);
      timeoutRef.current = null;
    }, 1000);
  };

  const handleChange = (newValue: string) => {
    const filter = list.filter(item => item.id === newValue);
    onOk(filter, false);
  };

  const onFocus = () => {
    if(list.length) {
      setTimeout(() => {
        if(!doubleClickRef.current) setOpen(true);
        doubleClickRef.current = null;
      }, 210)
    }
  };

  const onBlur = () => setOpen(false);
  
  const placeholder = localStorage.i18nextLng === 'en' ? options?.placeholderEn : options?.placeholder;

  return (
    <div className={styles.dataLinkLov}>
      <Select
        showSearch
        allowClear
        size='small'
        onSearch={onSearch}
        filterOption={false}
        style={{ width: '100%' }}
        disabled={disabled || options?.disabled}
        onClear={() => onOk([{}])}
        value={v || undefined}
        open={open}
        onFocus={onFocus}
        onBlur={onBlur}
        onClick={() => {
          if (doubleClickRef.current) {
            clearTimeout(doubleClickRef.current);
            copyToClipboard(value);
            return;
          }
          doubleClickRef.current = setTimeout(() => {
            doubleClickRef.current = null;
          }, 200);
        }}
        suffixIcon={<Icon onClick={onShow} icon="&#xe63b;" style={style} />}
        placeholder={placeholder}
        notFoundContent={null}
        onSelect={handleChange}
      >
        {list?.map(item => (
          <Select.Option value={item.id} key={item.id}>
            {Array.isArray(options.showFieldName) ? 
            options.showFieldName.map((field: { label: string; value: string}) => item[field.value]).join('-') 
            : item[options.showFieldName]}
          </Select.Option>
        ))}
      </Select>
      <ModalTableInModel
        showAutoSearch
        ref={modalTableRef}
        showSelected={options?.showFieldName}
        onOk={(data) => onOk(data)}
        model={model}
        rowSelectionType={options?.radio ? 'checkbox' : 'radio'}
        onCancel={onHide}
        visible={visible}
        handleQuerySet={handleQuerySet}
        handleResult={handleResult}
        treeStructure={options?.treeStructure}
        treeId={options?.treeId}
        treeParentId={options?.treeParentId}
      />
    </div>
  );
};

export default forwardRef(App);
